package com.wry.service.impl;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.converters.bigdecimal.BigDecimalStringConverter;
import com.alibaba.excel.converters.date.DateStringConverter;
import com.alibaba.excel.event.AnalysisEventListener;
import com.wry.service.DataImportService;
import com.wry.vo.ExpressDataImportVO;
import com.wry.vo.ExpressReconciliationExcelVO;
import com.wry.vo.GoodsVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * <h1>  <h1>
 *
 * @author 魏如元
 * @since 2022/9/6
 */
@Service
@Slf4j
public class DataImportServiceImpl implements DataImportService {

    @Override
    public void templateDownload(HttpServletResponse response) throws IOException {
        final ExcelWriter writer = getExcelWriter();
        final List<GoodsVO> voList = List.of(new GoodsVO());
        writer.write(voList, true);
        exportExcelResponse(response, writer);
    }

    /**
     * 构建输出 Excel 的响应对象
     *  @param response 响应对象
     * @param writer   Excel 写入器
     */
    private void exportExcelResponse(HttpServletResponse response, ExcelWriter writer) throws IOException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLUtil.encode("货品导入模板") + ".xlsx");
        ServletOutputStream out = response.getOutputStream();
        writer.flush(out, true);
        writer.close();
        IoUtil.close(out);
    }

    /**
     * 构建 Excel 导入导出表头
     *
     * @return Excel 写入器示例
     */
    private ExcelWriter getExcelWriter() {
        final ExcelWriter writer = ExcelUtil.getWriter();
        getExcelImportTableMap().forEach((k, v) -> writer.addHeaderAlias(v, k));
        return writer;
    }

    /**
     * 获取 Excel 导入的表头字段 Map 集合
     *
     * @return Excel 导入表头 Map 集合
     */
    private Map<String, String> getExcelImportTableMap() {
        final Map<String, String> resultMap = new LinkedHashMap<>(12);
        resultMap.put("#货品名称", "goodsName");
        resultMap.put("#商品条码", "barCode");
        resultMap.put("#数量","quantity");
        return resultMap;
    }

    @Override
    public String importGoods(MultipartFile file) throws IOException {
        List<GoodsVO> list = new ArrayList<>();
        EasyExcel.read(file.getInputStream(), GoodsVO.class, new AnalysisEventListener<GoodsVO>() {
            @Override
            public void invoke(GoodsVO goodsVO, AnalysisContext analysisContext) {
                list.add(goodsVO);
            }
            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
            }
        }).sheet().doRead();
        System.out.println(list);
        for (GoodsVO goodsVO : list) {
            System.out.println(goodsVO.getBarCode());
        }
        return checkDataNull(list);
    }

    private String checkDataNull(List<GoodsVO> list){
        for (GoodsVO goodsVO : list) {
            if (Objects.isNull(goodsVO.getGoodsName()) || Objects.isNull(goodsVO.getQuantity()) || Objects.isNull(goodsVO.getBarCode())) {
                System.out.println("必填字段存在空值，请检查！");
                return  "必填字段存在空值，请检查！";
            }
        }
        return "正在导入";
    }

    @Override
    public void importExpress(MultipartFile file, HttpServletResponse response) throws IOException {
        List<String> excelType = List.of(".xls", ".xlsx");
        final InputStream inputStream = file.getInputStream();
        String fileType = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf("."));
        if (!excelType.contains(fileType)){
            throw new RuntimeException("文件类型不正确！请上传后缀为.xls或.xlsx的文件！");
        }

        List<ExpressDataImportVO> expressDataExcelList = new ArrayList<>();
        EasyExcel.read(inputStream, ExpressDataImportVO.class, new AnalysisEventListener<ExpressDataImportVO>() {
            @Override
            public void invoke(ExpressDataImportVO expressData, AnalysisContext analysisContext) {
                expressDataExcelList.add(expressData);
            }
            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                log.info("Excel-解析完成");
            }
        }).sheet().doRead();
        inputStream.close();
        log.info("expressDataExcelList => {}",expressDataExcelList);

        handleExport(expressDataExcelList,  response);
    }

    private void handleExport(List<ExpressDataImportVO> expressDataExcelList, HttpServletResponse response) throws IOException {
       List<ExpressReconciliationExcelVO> excelVOList = new ArrayList<>();
        expressDataExcelList.forEach(expressDataImportVO -> {
            ExpressReconciliationExcelVO excelVO = new ExpressReconciliationExcelVO();
            excelVO.setExpressNumber(expressDataImportVO.getExpressNumber());
            excelVOList.add(excelVO);
        });


        EasyExcel.write(response.getOutputStream(), ExpressReconciliationExcelVO.class)
                //注册 WriteHandler ，getDefaultWriteHandler() 见下
                //注入原生 或 自定义转换器
                .registerConverter(new DateStringConverter())
                .registerConverter(new BigDecimalStringConverter())
                .sheet("这是指定要写入的sheet页")
                .doWrite(excelVOList );
    }

}
